package processing.main.clock;

import java.util.Date;

import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormatter;
import org.joda.time.format.ISODateTimeFormat;


/**
 * Event Class that contains all information about any given event.
 * Public Methods include 
 * 2 constructors, getCurrentTime, calculateHeight, printInfo, and printPrettyTime(DateTime) <-- static. 
 * @author jay
 */

public class Event {
	
	private static DateTime hoursAway1;
	private static DateTime hoursAway3;
	private static DateTime hoursAway6;
	private static DateTime hoursAway12;

	private String mEventName;
	private String mEventLocation;
	private DateTime mEventStartTime;
	private DateTime mEventEndTime;

	private float mTopPosition;
	private float mBottomPosition;
	private float mRectangleHeight;

	private float colorRed;
	private float colorGreen;
	private float colorBlue;
	private float colorAlpha;
	
	private static final float _HEIGHTNOW = 100, _HEIGHT1HR = 75,
			_HEIGHT3HR = 50, _HEIGHT6HR = 25, _HEIGHT12HR = 0;

	/**
	 * Constructor: Creates a Height Object
	 * 
	 * @param name
	 *            Name of the event
	 * @param location
	 *            Location of the event
	 * @param startTime
	 *            Event's Starting Time.
	 * @param endTime
	 *            Event's Ending Time.
	 */
	public Event(String name, String location, DateTime startTime,
			DateTime endTime) {

		if (name == null || name.equals("")) {
			mEventName = "No Event Name";
		} else {
			mEventName = name;
		}

		if (location == null || location.equals("")) {
			mEventLocation = "No Location";
		} else {
			mEventLocation = location;
		}

		if (startTime.toDate().compareTo(endTime.toDate()) <= 0) {
		}
		
		mEventStartTime = startTime;
		mEventEndTime = endTime;

		mTopPosition = calculateHeight(mEventStartTime);
		mBottomPosition = calculateHeight(mEventEndTime); 

		mRectangleHeight = mTopPosition - mBottomPosition; 
		
		colorRed = (float) (Math.random() % (255 - 195) + 195); 
		colorGreen = (float) (Math.random() % 254);
		colorGreen = (float) Math.random() % 50; 
		colorAlpha = (float)  (Math.random() % (255 - 155) + 155);
	}
	
	/**
	 * 
	 * @param name Name of event
	 * @param location Location of Event
	 * @param startTime Start Time in 24-hour clock.
	 * @param endTime End Time in 24-hour clock.
	 */
	public Event(String name, String location, String startTime,
			String endTime) {

		if (name == null || name.equals("")) {
			mEventName = "No Event Name";
		} else {
			mEventName = name;
		}

		if (location == null || location.equals("")) {
			mEventLocation = "No Location";
		} else {
			mEventLocation = location;
		}

		String[] startHoursAndMinutes = startTime.split(":");
		mEventStartTime = (new DateTime()).withHourOfDay(Integer.parseInt(startHoursAndMinutes[0]))
				.withMinuteOfHour(Integer.parseInt(startHoursAndMinutes[1]));
		
		String[] endHoursAndMinutes = endTime.split(":");

		mEventEndTime = (new DateTime()).withHourOfDay(Integer.parseInt(endHoursAndMinutes[0]))
				.withMinuteOfHour(Integer.parseInt(endHoursAndMinutes[1]));

		mTopPosition = calculateHeight(mEventStartTime);
		mBottomPosition = calculateHeight(mEventEndTime); 

		mRectangleHeight = mTopPosition - mBottomPosition; 
		
		colorRed = (float) (Math.random() % (255 - 195) + 195); 
		colorGreen = (float) (Math.random() % 254);
		colorGreen = (float) Math.random() % 50; 
		colorAlpha = (float)  (Math.random() % (255 - 155) + 155);
	}

	/**
	 * Returns the Current Time
	 * @return
	 */
	public static DateTime getCurrentTime() {
		return new DateTime();
	}

	/**
	 * Takes an event time and gives the height from 0 to 100.
	 * @param eventTime time of the event.
	 * @return the converted height from 0 to 100. If the time is before now, or after 12 hours, -1 is returned.
	 */
	public float calculateHeight(DateTime eventTime) {
		DateTime timeNow = getCurrentTime();
		hoursAway1 = timeNow.plusHours(1);
		hoursAway3 = timeNow.plusHours(3);
		hoursAway6 = timeNow.plusHours(6);
		hoursAway12 = timeNow.plusHours(12); 
		
		if(checkBetweenTimes(eventTime, new DateTime().minusYears(50), timeNow))
			return 100;
		if(checkBetweenTimes(eventTime, timeNow, hoursAway1))
			return calculateSubHeight(100, 75, 0, 1, eventTime, timeNow, hoursAway1);
		if(checkBetweenTimes(eventTime, hoursAway1, hoursAway3))
			return calculateSubHeight(75, 50, 1, 3, eventTime, hoursAway1, hoursAway3);
		if(checkBetweenTimes(eventTime, hoursAway3, hoursAway6))
			return calculateSubHeight(50, 25, 3, 6, eventTime, hoursAway3, hoursAway6);
		if(checkBetweenTimes(eventTime, hoursAway6, hoursAway12))
			return calculateSubHeight(25, 0, 6, 12, eventTime, hoursAway6, hoursAway12);
		if(checkBetweenTimes(eventTime, hoursAway12, new DateTime().plusYears(50)))
			return 0;
		
		System.out.println("Shouldn't get this far...");
		return -1;
	}


	/**
	 * Calculates the height of the eventTime relative to its top and bottom boundaries (e.g. 3hours away and 6hours away)
	 * @param topHeight
	 * @param bottomHeight
	 * @param topHours
	 * @param bottomHours
	 * @param eventTime
	 * @param topTime
	 * @param bottomTime
	 * @return the percentage corresponding to the Event's Time.
	 */
	private float calculateSubHeight(float topHeight, 
			float bottomHeight, 
			float topHours, 
			float bottomHours, 
			DateTime eventTime, 
			DateTime topTime, 
			DateTime bottomTime) {
		/*
		 * calculate how long it is between now and top time. now - 15 = 15 
		 * divide by range (top time - bottom time) 15 / (1hr - now) = .25 
		 * multiply by 25? .25 * 25 = 6.25
		 * subtract top position minus answer. 100 - 6.25 = 93.25 
		 * return subtraction 93.25		
		 */
		
		//get the range.
		float timeRange = 60 * (bottomHours - topHours);
		
		//calculate time between event and top time.
		float timeDifferenceInMinutes = 60 * 
				(eventTime.getHourOfDay() - topTime.getHourOfDay()) + 
				(eventTime.getMinuteOfHour() - topTime.getMinuteOfHour());
		
		if(timeDifferenceInMinutes < 0){
			timeDifferenceInMinutes += 60 * 24;
		}
		
		//divide by range.
		float ratioFromTop = timeDifferenceInMinutes / timeRange * 100; 
		
		//multiply by .25
		float scaledRatio = (float) .25 * ratioFromTop;
		
		//subtract top position minus answer. 
		float finalHeightInPercent = topHeight - scaledRatio;
		return finalHeightInPercent;
		
	}

	private boolean checkBetweenTimes(DateTime theTime, DateTime firstTime,
			DateTime secondTime) {
		Date theDate = theTime.toDate();
		Date firstDate = firstTime.toDate();
		Date secondDate = secondTime.toDate();

		if (theDate.compareTo(firstDate) >= 0
				&& theDate.compareTo(secondDate) < 0)
			return true;
		return false;
	}

	private DateTime addHoursAndMinutes(DateTime dt, int numHours,
			int numMinutes) {
		DateTime returnDt = new DateTime();
		returnDt = dt.plusHours(numHours);
		returnDt = dt.plusMinutes(numMinutes);

		return returnDt;
	}
	
	/**
	 * Prints out the event name, location, start time, top radius, end time, and end radius.
	 * For debugging purposes.
	 */
	public void printInfo(){
		System.out.println("=================");
		System.out.println(mEventName);
		System.out.println(mEventLocation);
		System.out.println("Start Time: " + printPrettyTime(this.mEventStartTime) + " " + mTopPosition);
		System.out.println("End Time: " + printPrettyTime(this.mEventEndTime) + " " + mBottomPosition);
		System.out.println("=================\n");
	}

	/**
	 * Returns a String in the form of HH:MM
	 * @param dt the DateTime to print.
	 * @return the string in the form of HH:MM
	 */
	public static String printPrettyTime(DateTime dt){
		DateTimeFormatter fmt = ISODateTimeFormat.hourMinute();
		String str = fmt.print(dt);
		return str;
	}
	
	/**
	 * @return the mEventName
	 */
	public String getEventName() {
		return mEventName;
	}


	/**
	 * @return the mEventLocation
	 */
	public String getEventLocation() {
		return mEventLocation;
	}


	/**
	 * @return the mEventStartTime
	 */
	public DateTime getEventStartTime() {
		return mEventStartTime;
	}


	/**
	 * @return the mEventEndTime
	 */
	public DateTime getEventEndTime() {
		return mEventEndTime;
	}


	/**
	 * @return the mTopPosition
	 */
	public float getTopPosition() {
		return mTopPosition/100;
	}


	/**
	 * @return the mBottomPosition
	 */
	public float getBottomPosition() {
		return mBottomPosition/100;
	}


	/**
	 * @return the mRectangleHeight
	 */
	public float getRectangleHeight() {
		return mRectangleHeight/100;
	}


	/**
	 * @return the colorRed
	 */
	public float getColorRed() {
		return colorRed;
	}


	/**
	 * @return the colorGreen
	 */
	public float getColorGreen() {
		return colorGreen;
	}


	/**
	 * @return the colorBlue
	 */
	public float getColorBlue() {
		return colorBlue;
	}


	/**
	 * @return the colorAlpha
	 */
	public float getColorAlpha() {
		return colorAlpha;
	}
}